package com.ebelter.btlibrary.btble.ble.bluetooth.device.impl;


import android.os.SystemClock;

import com.ebelter.btlibrary.btble.ble.bluetooth.device.IBleServerWriter;
import com.ebelter.btlibrary.btble.ble.bluetooth.device.InternalChannel;
import com.ebelter.btlibrary.btble.ble.model.BtAck;
import com.ebelter.btlibrary.btble.ble.model.BtRequest;
import com.ebelter.btlibrary.btble.util.BytesUtils;
import com.ebelter.btlibrary.util.ULog;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;

/**
 * 蓝牙指令编辑者，抽象层，具体由开发者实现，用于蓝牙数据协议，编辑蓝牙指令
 * Created by Sergio Pan on 2017/11/28.
 */
public abstract class BleCommandEditor implements InternalChannel {

    protected final static String TAG = "BleCommandEditor";
    private IBleServerWriter mBleMessageWriter;
    private StringBuffer sb;
    /*** 请求队列 ***/
    private ArrayList<BtRequest> mRequests = new ArrayList<>();
    /*** 响应的ACK ***/
    //private BtAck respAck;
    /*** 上一个请求的ACK ***/
 //   private BtAck preAck;
    /*** 停止线程 ***/
    private boolean isStop = false;
    protected byte dataHeaderSend;



    public void setDataHeaderSend(byte dataHeaderSend) {
        this.dataHeaderSend = dataHeaderSend;
    }

    public void registerBleMessageWriter(IBleServerWriter bleMessageWriter) {
        this.mBleMessageWriter = bleMessageWriter;
       // new Thread(ackRun).start();
    }

    //未加密的
    protected void sendBleMessage(String desc,byte[] data) {
        if (mBleMessageWriter != null) {
            ULog.i(TAG,"--sendBleMessage--desc="+desc+"--"+BytesUtils.bytes2HexStr(data));
            mBleMessageWriter.writeLlsAlertLevel(desc,encrypt(data));
        }

    }

    @Override
    public void sendCommnd(Object command) {
        onReceiveCommand(command);
    }

    protected abstract void onReceiveCommand(Object command);

    private static final byte[] deviceAddressBytes = new byte[]{0x16, 0x15, 0x14, 0x13, 0x12, 0x11};
    /**
     * 加密处理，默认为不加密，如数据需要加密，需重写此方法
     */
    public static byte[] encrypt(byte[] data){
        ULog.i(TAG, "----encript--- before --data = " + BytesUtils.bytes2HexStr(data));


        if ((data[0]&0xff)==(0xab & 0xff)&&(data[1]&0xff)==(0x02 & 0xff)&&(data[2]&0xff)==(0x9b & 0xff)&&(data[3]&0xff)==(0x17 & 0xff)&&data.length==4){
            ULog.i(TAG, "---加密遇到已经加过密的回应 历史数据 ACK 不需要加密了-");
            return data;
        }

        if ((data[0]&0xff)==(0xab & 0xff)&&(data[1]&0xff)==(0x02 & 0xff)&&(data[2]&0xff)==(0xa3 & 0xff)&&(data[3]&0xff)==(0x16 & 0xff)&&data.length==4){
            ULog.i(TAG, "---加密遇到已经加过密的回应 测量数据 ACK 不需要加密了-");
            return data;
        }

        if ((data[0] & 0xff) == (0xab & 0xff)) {
            for (int i = 3, j = 0; i < data.length; i++, j++) {
                data[i] ^= deviceAddressBytes[j % 6];
            }
        }
        ULog.i(TAG, "----encript-----data = " + BytesUtils.bytes2HexStr(data));
        return data;
    }

    @Override
    public void updateRespondAck(BtAck ack) {
      //  this.respAck = ack;
    }






    /**
     * 重发保障机制处理
     * 1.次数：最多3次
     * 2.间隔时间
     */
    private final Runnable ackRun = new Runnable() {

        @Override
        public void run() {

            while (!isStop) {
                if (mRequests!=null&&mRequests.size()>0){

                    BtRequest request = mRequests.get(0);
                    if (request != null && request.getData() != null) {
                     //   BtRequest request2=new BtRequest(request.getAck(),request.getData());
                        ULog.i(TAG,"数据池里面有数据 准备发送"+request.toString());
                        sendBleMessage(request.getAck(),request.getData());
                        mRequests.remove(0);
                    }
                }

                SystemClock.sleep(300);
            }
        }
    };

    public void stop() {
        isStop = true;
    }

    /**
     * 发送请求，自带消息重发机制实现
     */
    protected void sendResquest(String desc, byte[] bytes) {
        sendBleMessage(desc,bytes);
    }



    public void release() {
        //停止线程
        isStop = true;
        if (mRequests != null) {
            mRequests.clear();
        }
    }


}
